from __future__ import annotations

from app.data.database.components import ComponentType
from app.data.database.database import DB
from app.data.database.skill_components import SkillComponent, SkillTags

from app.engine import (action, banner, combat_calcs, engine, equations,
                        image_mods, item_funcs, item_system, skill_system)
from app.engine.game_state import game
from app.engine.objects.unit import UnitObject
from app.engine.source_type import SourceType
from app.engine.combat import playback as pb
from app.engine.movement import movement_funcs

from app.utilities import utils, static_random
from app.utilities.enums import Strike

import logging

# Importing methods
from app.engine.skill_components.advanced_components import get_proc_rate, get_weapon_filter
from app.engine.skill_components.charge_components import get_marks
from app.engine.skill_components.combat2_components import get_pc_damage


class EventBeforeCombat(SkillComponent):
    nid = 'event_before_combat'
    desc = 'Calls event before any combat'
    tag = SkillTags.ADVANCED

    expose = ComponentType.Event
    value = ''

    def start_combat(self, playback, unit: UnitObject, item, target: UnitObject, item2, mode):
        game.events.trigger_specific_event(self.value, unit, target, unit.position, {'item': item, 'item2': item2, 'mode': mode})
        
class EventAfterCombat(SkillComponent):
    nid = 'event_after_combat'
    desc = 'Calls event after any combat'
    tag = SkillTags.ADVANCED

    expose = ComponentType.Event
    value = ''

    def end_combat(self, playback, unit: UnitObject, item, target: UnitObject, item2, mode):
        game.events.trigger_specific_event(self.value, unit, target, unit.position, {'item': item, 'mode': mode, 'item2': item2})
        
class CostHP(SkillComponent):
    nid = 'cost_thp'
    desc = "Skill reduces THP with each use. Unit must have >=X THP to use the skill."
    tag = SkillTags.CHARGE

    expose = ComponentType.Int
    value = 2

    ignore_conditional = True

    def condition(self, unit, item):
        return unit.get_thp() >= self.value

    def start_combat(self, playback, unit, item, target, item2, mode):
        if self.skill.data.get('active'):
            action.do(action.ChangeTHP(unit, -self.value))
            
class RegenerationTHP(SkillComponent):
    nid = 'regeneration_THP'
    desc = "Unit restores given amount of THP at beginning of turn"
    tag = SkillTags.STATUS

    expose = ComponentType.Int
    value = 1

    def on_upkeep(self, actions, playback, unit):
        max_thp = unit.get_max_thp()
        if unit.get_thp() < max_thp:
            hp_change = int(self.value)
            actions.append(action.ChangeTHP(unit, hp_change))
            # Playback
            playback.append(pb.HitSound('MapHeal'))
            playback.append(pb.DamageNumbers(unit, -hp_change))
            if hp_change >= 30:
                name = 'MapBigHealTrans'
            elif hp_change >= 15:
                name = 'MapMediumHealTrans'
            else:
                name = 'MapSmallHealTrans'
            playback.append(pb.CastAnim(name))
            
class LostOnNextEndCombat(SkillComponent):
    nid = 'lost_on_next_end_combat'
    desc = "Remove after combat, but not, like, this one"
    tag = SkillTags.TIME

    expose = (ComponentType.NewMultipleOptions)

    options = {
        "lost_on_self": ComponentType.Bool,
        "lost_on_ally": ComponentType.Bool,
        "lost_on_enemy": ComponentType.Bool,
        "lost_on_splash": ComponentType.Bool,
        "only_if_initiated": ComponentType.Bool,
    }

    def __init__(self, value=None):
        self.value = {
            "lost_on_self": True,
            "lost_on_ally": True,
            "lost_on_enemy": True,
            "lost_on_splash": True,
            "only_if_initiated": False,
        }
        if value:
            self.value.update(value)
        self.marked_for_delete = 0

    def cleanup_combat_unconditional(self, playback, unit, item, target, item2, mode):
        self.marked_for_delete = self.marked_for_delete + 1

    def post_combat_unconditional(self, playback, unit, item, target, item2, mode):
        if not self.marked_for_delete >= 2:
            print(self.marked_for_delete)
            return
        from app.engine import skill_system
        # Skip this if the unit didn't initiate
        if self.value.get('only_if_initiated', False):
            if mode not in ("attack", "splash"):
                return
        remove_skill = False
        if self.value.get('lost_on_self', True):
            if unit == target:
                remove_skill = True
        if self.value.get('lost_on_ally', True):
            if target:
                if skill_system.check_ally(unit, target):
                    remove_skill = True
        if self.value.get('lost_on_enemy', True):
            if target:
                if skill_system.check_enemy(unit, target):
                    remove_skill = True
        if self.value.get('lost_on_splash', True):
            if not target:
                remove_skill = True

        if remove_skill:
            action.do(action.RemoveSkill(unit, self.skill))
        self.marked_for_delete = False

    def on_end_chapter_unconditional(self, unit, skill):
        action.do(action.RemoveSkill(unit, self.skill))
        self.marked_for_delete = 0